#include "RHIDescriptor.h"
#include "../../Core/CoreGlobals.h"
#include "../../Utils/LogUtil.h"
#include "../../Templates/NewObject.h"
#include "../RenderState.h"
#include "../../Game/Process/RenderProcess.h"

RHIDescriptor::Builder::Builder() noexcept = default;
RHIDescriptor::Builder::~Builder() noexcept = default;
RHIDescriptor::Builder::Builder(RHIDescriptor::Builder const& rhs) noexcept = default;
RHIDescriptor::Builder::Builder(RHIDescriptor::Builder && rhs) noexcept = default;
RHIDescriptor::Builder& RHIDescriptor::Builder::operator=(RHIDescriptor::Builder const& rhs) noexcept = default;
RHIDescriptor::Builder& RHIDescriptor::Builder::operator=(RHIDescriptor::Builder && rhs) noexcept = default;


RHIDescriptor::Builder& RHIDescriptor::Builder::SetDescriptorCount(uint32 index, uint32 count, bool isMultiple) noexcept
{
	mImpl->descriptorCounts.insert({ index, count });
	mImpl->descriptorMultiples.insert({ index, isMultiple });
	return *this;
}

RHIDescriptor::Builder& RHIDescriptor::Builder::PushShader(const std::string & name) noexcept
{
	ShaderPtr<RHIShader> shader(name);
	mImpl->shaderStages.push_back(shader);
	return *this;
}

ShaderPtr<RHIShader> RHIDescriptor::Builder::AddShader(const std::string & name) noexcept
{
	ShaderPtr<RHIShader> shader(name);
	mImpl->shaderStages.push_back(shader);
	return shader;
}

RefCountPtr<RHIDescriptor> RHIDescriptor::Builder::Build()
{
	assert(IsInRenderThread());
	return RefCountPtr<RHIDescriptor>(NewObject<RHIDescriptor>(*mImpl));
}

RefCountPtr<RHIDescriptor> RHIDescriptor::Builder::Build(RenderProcess * process, const std::string & name)
{
	assert(IsInRenderThread());
	RHIDescriptor* descriptor = NewObject<RHIDescriptor>(*mImpl);
	process->AddDescriptor(name, descriptor);
	return RefCountPtr<RHIDescriptor>(descriptor);
}

void RHIDescriptor::ReleaseResource()
{
	if (IsInRenderThread())
	{
		if (mProcess != nullptr)
		{
			mProcess->RemoveDescriptor(mName, this);
		}
		DeleteObject<RHIDescriptor>(this);
	}
	else
	{
		AsyncTask(GRenderThreadId, [this]() {
			if (mProcess != nullptr)
			{
				mProcess->RemoveDescriptor(mName, this);
			}
			DeleteObject<RHIDescriptor>(this);
			});
	}
}

RHIDescriptor::~RHIDescriptor()
{
	GRenderState->DelayGCPipelineLayout(mPipelineLayout);
	for (const auto& descriptorSetLayout : mDescriptorSetLayouts)
	{
		GRenderState->DelayGCDescriptorSetLayout(descriptorSetLayout);
	}
	if (mDescriptorPool != VK_NULL_HANDLE)
		GRenderState->DelayGCDescriptorPool(mDescriptorPool);
}

RHIDescriptor::RHIDescriptor(BuilderDetails & builderDetails)
{
	mSetIndex = UINT32_MAX;
	mOrderIndex = UINT32_MAX;

	mDescriptorPoolInlineUniformBlockCreateInfoEXT = {};
	mDescriptorPoolInlineUniformBlockCreateInfoEXT.sType = VK_STRUCTURE_TYPE_MAX_ENUM;
	// mDescriptorPoolInlineUniformBlockCreateInfoEXT.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT;

	mShaderStages.assign(builderDetails.shaderStages.begin(), builderDetails.shaderStages.end());
	mDescriptorCounts.insert(builderDetails.descriptorCounts.begin(), builderDetails.descriptorCounts.end());
	mDescriptorMultiples.insert(builderDetails.descriptorMultiples.begin(), builderDetails.descriptorMultiples.end());

	std::map<uint32, VkPushConstantRange> pushConstantRangeTable;
	// Get layout
	for (auto& shaderStage : mShaderStages)
	{
		// assign shader
		shaderStage.ActiveShader(this);

		for (const auto& shaderParamIter : shaderStage->mShaderParams)
		{
			// insert shader params
			if (mShaderParams.find(shaderParamIter.first) == mShaderParams.end())
			{
				mShaderParams.insert(shaderParamIter);
			}


			bool isExist = false;
			const ShaderParam* shaderParam = shaderParamIter.second;
			if (mDescriptorTable.find(shaderParam->mSet) != mDescriptorTable.end())
			{
				std::map<uint32, DescriptorNode>& descriptorNodeMap = mDescriptorTable[shaderParam->mSet];
				if (descriptorNodeMap.find(shaderParam->mBinging) != descriptorNodeMap.end())
				{
					DescriptorNode& descriptorNode = descriptorNodeMap[shaderParam->mBinging];
					assert(descriptorNode.descriptorSetLayoutBinding.descriptorCount == shaderParam->mCount);
					assert(descriptorNode.descriptorSetLayoutBinding.descriptorType == shaderParam->mType);
					descriptorNode.descriptorSetLayoutBinding.stageFlags = descriptorNode.descriptorSetLayoutBinding.stageFlags | shaderStage->GetShaderStage();

					isExist = true;
				}
			}
			else
			{
				// Insert a new map
				std::map<uint32, DescriptorNode> descriptorNodeMap;
				mDescriptorTable.insert({ shaderParam->mSet, descriptorNodeMap });
			}

			if (!isExist)
			{
				// Get the map
				std::map<uint32, DescriptorNode>& descriptorNodeMap = mDescriptorTable[shaderParam->mSet];
				// Insert a new node
				descriptorNodeMap.insert({ shaderParam->mBinging, DescriptorNode() });
				// get the node
				DescriptorNode& descriptorNode = descriptorNodeMap[shaderParam->mBinging];

				// Set value
				descriptorNode.descriptorSetLayoutBinding.binding = shaderParam->mBinging;
				descriptorNode.descriptorSetLayoutBinding.descriptorCount = shaderParam->mCount;
				descriptorNode.descriptorSetLayoutBinding.descriptorType = shaderParam->mType;
				descriptorNode.descriptorSetLayoutBinding.stageFlags = shaderStage->GetShaderStage();

				descriptorNode.writeDescriptorSet.dstBinding = shaderParam->mBinging;
				descriptorNode.writeDescriptorSet.descriptorCount = shaderParam->mCount;
				descriptorNode.writeDescriptorSet.descriptorType = shaderParam->mType;

				switch (shaderParam->mType)
				{
				case VK_DESCRIPTOR_TYPE_SAMPLER:
				case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
				case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
				case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
				case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
					descriptorNode.imageInfos.resize(shaderParam->mCount, {});
					descriptorNode.writeDescriptorSet.pImageInfo = descriptorNode.imageInfos.data();
					break;
				case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
				case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
					descriptorNode.bufferViews.resize(shaderParam->mCount, VK_NULL_HANDLE);
					descriptorNode.writeDescriptorSet.pTexelBufferView = descriptorNode.bufferViewInfos.data();
					break;
				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
					descriptorNode.bufferInfos.resize(shaderParam->mCount, {});
					descriptorNode.writeDescriptorSet.pBufferInfo = descriptorNode.bufferInfos.data();
					break;
				case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
					// Make sure only one this type in shader group
					// I dont know how to use more this type
					assert(mDescriptorPoolInlineUniformBlockCreateInfoEXT.sType == VK_STRUCTURE_TYPE_MAX_ENUM);
					mDescriptorPoolInlineUniformBlockCreateInfoEXT.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT;
					// This value is set count
					mDescriptorPoolInlineUniformBlockCreateInfoEXT.maxInlineUniformBlockBindings = mDescriptorCounts[shaderParam->mSet];

					// This count is data size
					descriptorNode.inlineWrite.dataSize = shaderParam->mCount;
					descriptorNode.writeDescriptorSet.pNext = &descriptorNode.inlineWrite;
					break;
				case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
					descriptorNode.tlasInfos.resize(shaderParam->mCount, VK_NULL_HANDLE);
					descriptorNode.tlasWrite.accelerationStructureCount = shaderParam->mCount;
					descriptorNode.tlasWrite.pAccelerationStructures = descriptorNode.tlasInfos.data();
					descriptorNode.writeDescriptorSet.pNext = &descriptorNode.tlasWrite;
					break;
				}
			}

		}

		// Get push constants
		if (shaderStage->GetPushConstantRange().stageFlags != VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM)
		{
			if (pushConstantRangeTable.find(shaderStage->GetPushConstantRange().offset) != pushConstantRangeTable.end())
			{
				VkPushConstantRange& pushConstantRange = pushConstantRangeTable[shaderStage->GetPushConstantRange().offset];
				assert(pushConstantRange.size == shaderStage->GetPushConstantRange().size);
				pushConstantRange.stageFlags = pushConstantRange.stageFlags | shaderStage->GetShaderStage();
			}
			else
			{
				pushConstantRangeTable.insert({ shaderStage->GetPushConstantRange().offset, shaderStage->GetPushConstantRange() });
			}
		}
	}


	// Get sort pushConstantRange and check offset
	uint32 offset = 0;
	for (const auto& pushConstantRange : pushConstantRangeTable)
	{
		assert(pushConstantRange.second.offset == offset);
		offset += pushConstantRange.second.size;
		mPushConstantRanges.push_back(pushConstantRange.second);
	}

	// Make sure the set num is suit shader set num
	assert(mDescriptorCounts.size() == mDescriptorTable.size());
	// Use to store the size for every set
	uint32 maxSetCount = 0;
	std::unordered_map<VkDescriptorType, uint32> descriptorPoolSizeMap;

	// Resize mDescriptorSetTable
	mDescriptorSetTable.resize(mDescriptorCounts.size(), std::vector<VkDescriptorSet>());

	// Check set and binging continuity and create descriptorSetLayout
	uint32 indexSet = 0;
	mDescriptorSetLayouts.resize(mDescriptorTable.size());
	for (const auto& descriptorMap : mDescriptorTable)
	{
		assert(indexSet == descriptorMap.first);
		uint32 indexBinding = 0;

		uint32 setCount = mDescriptorCounts[indexSet];
		if (mDescriptorMultiples[indexSet])
		{
			setCount *= GRenderState->GetFrameCount();
		}

		maxSetCount += setCount;

		mDescriptorSetTable[indexSet].resize(setCount);

		std::vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings;
		for (const auto& descriptorNodeMap : descriptorMap.second)
		{
			assert(indexBinding == descriptorNodeMap.first);

			VkDescriptorType descriptorType = descriptorNodeMap.second.descriptorSetLayoutBinding.descriptorType;
			uint32 descriptorCount = descriptorNodeMap.second.descriptorSetLayoutBinding.descriptorCount;

			// Calc pool size
			if (descriptorPoolSizeMap.find(descriptorType) != descriptorPoolSizeMap.end())
			{
				descriptorPoolSizeMap[descriptorType] += descriptorCount * setCount;
			}
			else
			{
				descriptorPoolSizeMap.insert({ descriptorType, descriptorCount * setCount });
			}

			descriptorSetLayoutBindings.push_back(descriptorNodeMap.second.descriptorSetLayoutBinding);

			indexBinding++;
		}
		// Create descriptorSetLayout
		VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo{};
		descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
		descriptorSetLayoutCreateInfo.bindingCount = static_cast<uint32>(descriptorSetLayoutBindings.size());
		descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings.data();
		VK_CHECK_RESULT(vkCreateDescriptorSetLayout(GVulkanRHI->GetLogicalDevice(), &descriptorSetLayoutCreateInfo, nullptr, &mDescriptorSetLayouts[indexSet]));
		indexSet++;
	}

	// Create pipeline layout
	VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo{};
	pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;

	pipelineLayoutCreateInfo.setLayoutCount = static_cast<uint32>(mDescriptorSetLayouts.size());
	pipelineLayoutCreateInfo.pSetLayouts = mDescriptorSetLayouts.data();

	pipelineLayoutCreateInfo.pushConstantRangeCount = static_cast<uint32>(mPushConstantRanges.size());
	pipelineLayoutCreateInfo.pPushConstantRanges = mPushConstantRanges.data();
	VK_CHECK_RESULT(vkCreatePipelineLayout(GVulkanRHI->GetLogicalDevice(), &pipelineLayoutCreateInfo, nullptr, &mPipelineLayout));



	std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
	for (const auto& descriptorPoolSizeIter : descriptorPoolSizeMap)
	{
		VkDescriptorPoolSize descriptorPoolSize{};
		descriptorPoolSize.type = descriptorPoolSizeIter.first;
		descriptorPoolSize.descriptorCount = descriptorPoolSizeIter.second;
		descriptorPoolSizes.push_back(descriptorPoolSize);
	}

	mDescriptorPool = VK_NULL_HANDLE;

	// Create descriptor pool
	VkDescriptorPoolCreateInfo descriptorPoolCreateInfo{};
	descriptorPoolCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
	descriptorPoolCreateInfo.poolSizeCount = static_cast<uint32>(descriptorPoolSizes.size());
	descriptorPoolCreateInfo.pPoolSizes = descriptorPoolSizes.data();
	descriptorPoolCreateInfo.maxSets = maxSetCount;
	if (mDescriptorPoolInlineUniformBlockCreateInfoEXT.sType != VK_STRUCTURE_TYPE_MAX_ENUM)
	{
		descriptorPoolCreateInfo.pNext = &mDescriptorPoolInlineUniformBlockCreateInfoEXT;
	}
	if (descriptorPoolCreateInfo.poolSizeCount > 0)
		VK_CHECK_RESULT(vkCreateDescriptorPool(GVulkanRHI->GetLogicalDevice(), &descriptorPoolCreateInfo, nullptr, &mDescriptorPool));


	// Alloc descript sets
	VkDescriptorSetAllocateInfo descriptorSetAllocateInfo{};
	descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
	descriptorSetAllocateInfo.descriptorPool = mDescriptorPool;

	for (uint32 i = 0; i < mDescriptorSetTable.size(); ++i)
	{
		std::vector<VkDescriptorSetLayout> descriptorSetLayouts;
		descriptorSetLayouts.resize(mDescriptorSetTable[i].size(), mDescriptorSetLayouts[i]);

		descriptorSetAllocateInfo.pSetLayouts = descriptorSetLayouts.data();
		descriptorSetAllocateInfo.descriptorSetCount = mDescriptorSetTable[i].size();

		VK_CHECK_RESULT(vkAllocateDescriptorSets(GVulkanRHI->GetLogicalDevice(), &descriptorSetAllocateInfo, mDescriptorSetTable[i].data()));
	}
}

void RHIDescriptor::UpdateDescriptor(const DescriptorMask & descriptorMask, bool isMultiple)
{
	assert(descriptorMask.setIndex != UINT32_MAX);
	assert(descriptorMask.orderIndex != UINT32_MAX);

	const uint32 frameCount = mDescriptorMultiples[descriptorMask.setIndex] ? GRenderState->GetFrameCount() : 1;
	assert(descriptorMask.descriptorSets.size() == frameCount);

	for (uint32 i = 0; i < frameCount; ++i)
	{
		assert(mDescriptorSetTable[descriptorMask.setIndex][descriptorMask.orderIndex * frameCount + i] == descriptorMask.descriptorSets[i]);
	}

	if (isMultiple)
	{
		for (uint32 i = 0; i < frameCount; ++i)
		{
			std::vector<VkWriteDescriptorSet> writeDescriptorSets;
			for (auto& descriptorNodeIter : mDescriptorTable[descriptorMask.setIndex])
			{
				DescriptorNode& descriptorNode = descriptorNodeIter.second;
				// Just update changes
				if (descriptorNode.isAssign)
				{
					// Set value for write
					SetValueForWrite(i, descriptorNode);
					// Set descriptorset
					descriptorNode.writeDescriptorSet.dstSet = descriptorMask.descriptorSets[i];
					// Push to the vector
					writeDescriptorSets.push_back(descriptorNode.writeDescriptorSet);
				}
			}

			// Update descript set
			vkUpdateDescriptorSets(GVulkanRHI->GetLogicalDevice(), static_cast<uint32>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
		}
	}
	else
	{
		const uint32 frameIndex = GRenderState->GetFrameIndex();

		std::vector<VkWriteDescriptorSet> writeDescriptorSets;
		for (auto& descriptorNodeIter : mDescriptorTable[descriptorMask.setIndex])
		{
			DescriptorNode& descriptorNode = descriptorNodeIter.second;
			// Just update changes
			if (descriptorNode.isAssign)
			{
				// Set value for write
				SetValueForWrite(frameIndex, descriptorNode);
				// Set descriptorset
				descriptorNode.writeDescriptorSet.dstSet = descriptorMask.descriptorSets[frameIndex];
				// Push to the vector
				writeDescriptorSets.push_back(descriptorNode.writeDescriptorSet);
			}
		}

		// Update descript set
		vkUpdateDescriptorSets(GVulkanRHI->GetLogicalDevice(), static_cast<uint32>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
	}

	for (auto& descriptorNodeIter : mDescriptorTable[descriptorMask.setIndex])
	{
		// reset the assign state
		descriptorNodeIter.second.isAssign = false;
		descriptorNodeIter.second.ClearStore();
	}

	// reset mSetIndex
	mSetIndex = UINT32_MAX;
}

DescriptorMask RHIDescriptor::AllocateDescriptor()
{
	assert(mSetIndex != UINT32_MAX);

	if (mOrderIndex == UINT32_MAX)
	{
		mOrderIndex = 0;
	}
	else
	{
		mOrderIndex++;
		// Make sure the descriptset index < count
		assert(mOrderIndex < mDescriptorCounts[mSetIndex]);
	}

	// Create mask
	DescriptorMask descriptorMask(mSetIndex, mOrderIndex);

	// Each frame has one set
	const uint32 frameCount = mDescriptorMultiples[mSetIndex] ? GRenderState->GetFrameCount() : 1;
	descriptorMask.descriptorSets.resize(frameCount);

	std::vector<VkWriteDescriptorSet> writeDescriptorSets;
	writeDescriptorSets.resize(mDescriptorTable[mSetIndex].size(), {});

	// Get the descriptorset in order
	for (uint32 i = 0; i < frameCount; ++i)
	{
		descriptorMask.descriptorSets[i] = mDescriptorSetTable[mSetIndex][mOrderIndex * frameCount + i];

		uint32 j = 0;
		for (auto& descriptorNodeIter : mDescriptorTable[mSetIndex])
		{
			DescriptorNode& descriptorNode = descriptorNodeIter.second;
			// Make sure this descriptorset all resource are assign
			assert(descriptorNode.isAssign);
			// Set value for write
			SetValueForWrite(i, descriptorNode);
			// Set descriptorset
			descriptorNode.writeDescriptorSet.dstSet = descriptorMask.descriptorSets[i];
			// Push to the vector
			writeDescriptorSets[j] = descriptorNode.writeDescriptorSet;

			j++;
		}

		// Update descript set
		vkUpdateDescriptorSets(GVulkanRHI->GetLogicalDevice(), static_cast<uint32>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
	}

	for (auto& descriptorNodeIter : mDescriptorTable[mSetIndex])
	{
		// reset the assign state
		descriptorNodeIter.second.isAssign = false;
		descriptorNodeIter.second.ClearStore();
	}

	// reset mOrderIndex if current orderIndex is the last one of current setIndex
	if (mOrderIndex == mDescriptorCounts[mSetIndex] - 1)
	{
		mOrderIndex = UINT32_MAX;
	}

	// reset mSetIndex
	mSetIndex = UINT32_MAX;

	return descriptorMask;
}

VkPipelineVertexInputStateCreateInfo& RHIDescriptor::GetVertexInputStateCreateInfo()
{
	for (const auto& shaderStage : mShaderStages)
	{
		if (shaderStage->GetShaderStage() == VK_SHADER_STAGE_VERTEX_BIT)
		{
			return shaderStage->GetVertexInputStateCreateInfo();
		}
	}
	// No Vertex shader, error
	assert(0);
	return mShaderStages[0]->GetVertexInputStateCreateInfo();
}

VkPipelineInputAssemblyStateCreateInfo& RHIDescriptor::GetInputAssemblyStateCreateInfo()
{
	for (const auto& shaderStage : mShaderStages)
	{
		if (shaderStage->GetShaderStage() == VK_SHADER_STAGE_VERTEX_BIT)
		{
			return shaderStage->GetInputAssemblyStateCreateInfo();
		}
	}
	// No Vertex shader, error
	assert(0);
	return mShaderStages[0]->GetInputAssemblyStateCreateInfo();
}

std::vector<ShaderPtr<RHIShader>>& RHIDescriptor::GetShaderStages()
{
	return mShaderStages;
}

VkPipelineLayout RHIDescriptor::GetPipelineLayout() const
{
	return mPipelineLayout;
}

ShaderParam* RHIDescriptor::GetParamInfo(const std::string & name) const
{
	if (mShaderParams.find(name) != mShaderParams.end())
		return mShaderParams.find(name)->second;
	assert(0);
	return nullptr;
}

void RHIDescriptor::SetValue(const std::string & name, RefCountPtr<RHISampler> sampler)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount == 1);
	assert(shaderParam->mType == VK_DESCRIPTOR_TYPE_SAMPLER);
	SetSAMPLER(shaderParam, sampler);
}

void RHIDescriptor::SetValues(const std::string & name, const std::vector<RefCountPtr<RHISampler>>&samplers)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount > 1);
	assert(shaderParam->mType == VK_DESCRIPTOR_TYPE_SAMPLER);
	SetSAMPLERs(shaderParam, samplers);
}

void RHIDescriptor::SetValue(const std::string & name, RefCountPtr<RHITexture> texture, RefCountPtr<RHISampler> sampler, VkImageLayout layout)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount == 1);
	assert(shaderParam->mType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
	SetCOMBINED_IMAGE_SAMPLER(shaderParam, texture, sampler, layout);
}

void RHIDescriptor::SetValues(const std::string & name, const std::vector<RefCountPtr<RHITexture>>&textures, const std::vector<RefCountPtr<RHISampler>>&samplers, std::vector<VkImageLayout> layouts)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount > 1);
	assert(shaderParam->mType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
	if (layouts.size() == 0)
	{
		layouts.resize(shaderParam->mCount, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
	}
	SetCOMBINED_IMAGE_SAMPLERs(shaderParam, textures, samplers, layouts);
}

void RHIDescriptor::SetValue(const std::string & name, RefCountPtr<RHITexture> texture, VkImageLayout layout)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount == 1);
	switch (shaderParam->mType)
	{
	case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
		SetSAMPLED_IMAGE(shaderParam, texture, layout);
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		SetSTORAGE_IMAGE(shaderParam, texture, layout);
		break;
	default:
		assert(0);
		break;
	}
}

void RHIDescriptor::SetValues(const std::string & name, const std::vector<RefCountPtr<RHITexture>>&textures, std::vector<VkImageLayout> layouts)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount > 1);
	if (layouts.size() == 0)
	{
		layouts.resize(shaderParam->mCount, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
	}
	switch (shaderParam->mType)
	{
	case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
		SetSAMPLED_IMAGEs(shaderParam, textures, layouts);
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		SetSTORAGE_IMAGEs(shaderParam, textures, layouts);
		break;
	default:
		assert(0);
		break;
	}
}

void RHIDescriptor::SetValue(const std::string & name, RefCountPtr<RenderTarget> texture, VkImageLayout layout)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount == 1);
	assert(shaderParam->mType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
	SetINPUT_ATTACHMENT(shaderParam, texture, layout);
}

void RHIDescriptor::SetValue(const std::string & name, RefCountPtr<BufferView> bufferView)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount == 1);
	switch (shaderParam->mType)
	{
	case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
		SetUNIFORM_TEXEL_BUFFER(shaderParam, bufferView);
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
		SetSTORAGE_TEXEL_BUFFER(shaderParam, bufferView);
		break;
	default:
		assert(0);
		break;
	}
}

void RHIDescriptor::SetValues(const std::string & name, const std::vector<RefCountPtr<BufferView>>&bufferViews)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount > 1);
	switch (shaderParam->mType)
	{
	case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
		SetUNIFORM_TEXEL_BUFFERs(shaderParam, bufferViews);
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
		SetSTORAGE_TEXEL_BUFFERs(shaderParam, bufferViews);
		break;
	default:
		assert(0);
		break;
	}
}

void RHIDescriptor::SetValue(const std::string & name, RefCountPtr<RHIBuffer> buffer, VkDeviceSize offset, VkDeviceSize range)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount == 1);
	switch (shaderParam->mType)
	{
	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
		SetUNIFORM_BUFFER(shaderParam, buffer, offset, range);
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
		SetSTORAGE_BUFFER(shaderParam, buffer, offset, range);
		break;
	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
		SetUNIFORM_BUFFER_DYNAMIC(shaderParam, buffer, offset, range);
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
		SetSTORAGE_BUFFER_DYNAMIC(shaderParam, buffer, offset, range);
		break;
	default:
		assert(0);
		break;
	}
}

void RHIDescriptor::SetValues(const std::string & name, const std::vector<RefCountPtr<RHIBuffer>>&buffers, std::vector<VkDeviceSize> offsets, std::vector<VkDeviceSize> ranges)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount > 1);
	if (offsets.size() == 0)
	{
		offsets.resize(shaderParam->mCount, 0);
	}
	if (ranges.size() == 0)
	{
		ranges.resize(shaderParam->mCount, VK_WHOLE_SIZE);
	}
	switch (shaderParam->mType)
	{
	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
		SetUNIFORM_BUFFERs(shaderParam, buffers, offsets, ranges);
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
		SetSTORAGE_BUFFERs(shaderParam, buffers, offsets, ranges);
		break;
	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
		SetUNIFORM_BUFFER_DYNAMICs(shaderParam, buffers, offsets, ranges);
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
		SetSTORAGE_BUFFER_DYNAMICs(shaderParam, buffers, offsets, ranges);
		break;
	default:
		assert(0);
		break;
	}
}

void RHIDescriptor::SetValue(const std::string & name, void* value)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount == 1);
	assert(shaderParam->mType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT);
	SetINLINE_UNIFORM_BLOCK_EXT(shaderParam, value);
}

void RHIDescriptor::SetValue(const std::string & name, RefCountPtr<AccelerationStructure> topLevelAS)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount == 1);
	assert(shaderParam->mType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
	SetACCELERATION_STRUCTURE_KHR(shaderParam, topLevelAS);
}

void RHIDescriptor::SetValues(const std::string & name, const std::vector<RefCountPtr<AccelerationStructure>>&topLevelASs)
{
	assert(mShaderParams.find(name) != mShaderParams.end());
	ShaderParam* shaderParam = mShaderParams.find(name)->second;
	assert(shaderParam->mCount > 1);
	assert(shaderParam->mType == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR);
	SetACCELERATION_STRUCTURE_KHRs(shaderParam, topLevelASs);
}

void RHIDescriptor::CheckSetIndex(uint32 setIndex)
{
	if (mSetIndex == UINT32_MAX)
	{
		mSetIndex = setIndex;
		return;
	}
	// Make sure finish current set resource until deal next set
	assert(mSetIndex == setIndex);
}

void RHIDescriptor::SetSAMPLER(ShaderParam * shaderParam, RefCountPtr<RHISampler> sampler)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(sampler.IsValid());
	descriptorNode.imageInfos[0].sampler = sampler->GetSampler();
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSAMPLERs(ShaderParam * shaderParam, const std::vector<RefCountPtr<RHISampler>>&samplers)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(samplers.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(samplers[i].IsValid());
		descriptorNode.imageInfos[i].sampler = samplers[i]->GetSampler();
	}
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetCOMBINED_IMAGE_SAMPLER(ShaderParam * shaderParam, RefCountPtr<RHITexture> texture, RefCountPtr<RHISampler> sampler, VkImageLayout layout)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(texture.IsValid());
	assert(sampler.IsValid());
	// descriptorNode.imageInfos[0].imageView = texture->GetImageView();
	descriptorNode.textures.push_back(texture);
	descriptorNode.imageInfos[0].sampler = sampler->GetSampler();
	descriptorNode.imageInfos[0].imageLayout = layout;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetCOMBINED_IMAGE_SAMPLERs(ShaderParam * shaderParam, const std::vector<RefCountPtr<RHITexture>>&textures, const std::vector<RefCountPtr<RHISampler>>&samplers, const std::vector<VkImageLayout>&layouts)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(textures.size() == shaderParam->mCount);
	assert(samplers.size() == shaderParam->mCount);
	assert(layouts.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(textures[i].IsValid());
		assert(samplers[i].IsValid());
		// descriptorNode.imageInfos[i].imageView = textures[i]->GetImageView();
		descriptorNode.imageInfos[i].sampler = samplers[i]->GetSampler();
		descriptorNode.imageInfos[i].imageLayout = layouts[i];
	}
	descriptorNode.textures.assign(textures.begin(), textures.end());

	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSAMPLED_IMAGE(ShaderParam * shaderParam, RefCountPtr<RHITexture> texture, VkImageLayout layout)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(texture.IsValid());
	// descriptorNode.imageInfos[0].imageView = texture->GetImageView();
	descriptorNode.textures.push_back(texture);
	descriptorNode.imageInfos[0].imageLayout = layout;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSAMPLED_IMAGEs(ShaderParam * shaderParam, const std::vector<RefCountPtr<RHITexture>>&textures, const std::vector<VkImageLayout>&layouts)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(textures.size() == shaderParam->mCount);
	assert(layouts.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(textures[i].IsValid());
		// descriptorNode.imageInfos[i].imageView = textures[i]->GetImageView();
		descriptorNode.imageInfos[i].imageLayout = layouts[i];
	}
	descriptorNode.textures.assign(textures.begin(), textures.end());
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSTORAGE_IMAGE(ShaderParam * shaderParam, RefCountPtr<RHITexture> texture, VkImageLayout layout)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(texture.IsValid());
	// descriptorNode.imageInfos[0].imageView = texture->GetImageView();
	descriptorNode.textures.push_back(texture);
	descriptorNode.imageInfos[0].imageLayout = layout;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSTORAGE_IMAGEs(ShaderParam * shaderParam, const std::vector<RefCountPtr<RHITexture>>&textures, const std::vector<VkImageLayout>&layouts)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(textures.size() == shaderParam->mCount);
	assert(layouts.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(textures[i].IsValid());
		// descriptorNode.imageInfos[i].imageView = textures[i]->GetImageView();
		descriptorNode.imageInfos[i].imageLayout = layouts[i];
	}
	descriptorNode.textures.assign(textures.begin(), textures.end());
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetINPUT_ATTACHMENT(ShaderParam * shaderParam, RefCountPtr<RenderTarget> texture, VkImageLayout layout)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(texture.IsValid());
	// descriptorNode.imageInfos[0].imageView = texture->GetImageView();
	descriptorNode.textures.push_back(texture);
	descriptorNode.imageInfos[0].imageLayout = layout;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetUNIFORM_TEXEL_BUFFER(ShaderParam * shaderParam, RefCountPtr<BufferView> bufferView)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(bufferView.IsValid());
	// descriptorNode.bufferViews[0] = bufferView->GetBufferView();
	descriptorNode.bufferViews.push_back(bufferView);
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetUNIFORM_TEXEL_BUFFERs(ShaderParam * shaderParam, const std::vector<RefCountPtr<BufferView>>&bufferViews)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(bufferViews.size() == shaderParam->mCount);
	/*for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(bufferViews[i].IsValid());
		descriptorNode.bufferViews[i] = bufferViews[i]->GetBufferView();
	}*/
	descriptorNode.bufferViews.assign(bufferViews.begin(), bufferViews.end());
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSTORAGE_TEXEL_BUFFER(ShaderParam * shaderParam, RefCountPtr<BufferView> bufferView)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(bufferView.IsValid());
	// descriptorNode.bufferViews[0] = bufferView->GetBufferView();
	descriptorNode.bufferViews.push_back(bufferView);
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSTORAGE_TEXEL_BUFFERs(ShaderParam * shaderParam, const std::vector<RefCountPtr<BufferView>>&bufferViews)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(bufferViews.size() == shaderParam->mCount);
	/*for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(bufferViews[i].IsValid());
		descriptorNode.bufferViews[i] = bufferViews[i]->GetBufferView();
	}*/
	descriptorNode.bufferViews.assign(bufferViews.begin(), bufferViews.end());
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetUNIFORM_BUFFER(ShaderParam * shaderParam, RefCountPtr<RHIBuffer> buffer, VkDeviceSize offset, VkDeviceSize range)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(buffer.IsValid());
	// descriptorNode.bufferInfos[0].buffer = buffer->GetBuffer();
	descriptorNode.buffers.push_back(buffer);
	descriptorNode.bufferInfos[0].offset = offset;
	descriptorNode.bufferInfos[0].range = range;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetUNIFORM_BUFFERs(ShaderParam * shaderParam, const std::vector<RefCountPtr<RHIBuffer>>&buffers, const std::vector<VkDeviceSize>&offsets, const std::vector<VkDeviceSize>&ranges)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(buffers.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(buffers[i].IsValid());
		// descriptorNode.bufferInfos[i].buffer = buffers[i]->GetBuffer();
		descriptorNode.bufferInfos[i].offset = offsets[i];
		descriptorNode.bufferInfos[i].range = ranges[i];
	}
	descriptorNode.buffers.assign(buffers.begin(), buffers.end());
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSTORAGE_BUFFER(ShaderParam * shaderParam, RefCountPtr<RHIBuffer> buffer, VkDeviceSize offset, VkDeviceSize range)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(buffer.IsValid());
	// descriptorNode.bufferInfos[0].buffer = buffer->GetBuffer();
	descriptorNode.buffers.push_back(buffer);
	descriptorNode.bufferInfos[0].offset = offset;
	descriptorNode.bufferInfos[0].range = range;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSTORAGE_BUFFERs(ShaderParam * shaderParam, const std::vector<RefCountPtr<RHIBuffer>>&buffers, const std::vector<VkDeviceSize>&offsets, const std::vector<VkDeviceSize>&ranges)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(buffers.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(buffers[i].IsValid());
		// descriptorNode.bufferInfos[i].buffer = buffers[i]->GetBuffer();
		descriptorNode.bufferInfos[i].offset = offsets[i];
		descriptorNode.bufferInfos[i].range = ranges[i];
	}
	descriptorNode.buffers.assign(buffers.begin(), buffers.end());
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetUNIFORM_BUFFER_DYNAMIC(ShaderParam * shaderParam, RefCountPtr<RHIBuffer> buffer, VkDeviceSize offset, VkDeviceSize range)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(buffer.IsValid());
	// descriptorNode.bufferInfos[0].buffer = buffer->GetBuffer();
	descriptorNode.buffers.push_back(buffer);
	descriptorNode.bufferInfos[0].offset = offset;
	descriptorNode.bufferInfos[0].range = range;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetUNIFORM_BUFFER_DYNAMICs(ShaderParam * shaderParam, const std::vector<RefCountPtr<RHIBuffer>>&buffers, const std::vector<VkDeviceSize>&offsets, const std::vector<VkDeviceSize>&ranges)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(buffers.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(buffers[i].IsValid());
		// descriptorNode.bufferInfos[i].buffer = buffers[i]->GetBuffer();
		descriptorNode.bufferInfos[i].offset = offsets[i];
		descriptorNode.bufferInfos[i].range = ranges[i];
	}
	descriptorNode.buffers.assign(buffers.begin(), buffers.end());
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSTORAGE_BUFFER_DYNAMIC(ShaderParam * shaderParam, RefCountPtr<RHIBuffer> buffer, VkDeviceSize offset, VkDeviceSize range)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(buffer.IsValid());
	// descriptorNode.bufferInfos[0].buffer = buffer->GetBuffer();
	descriptorNode.buffers.push_back(buffer);
	descriptorNode.bufferInfos[0].offset = offset;
	descriptorNode.bufferInfos[0].range = range;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetSTORAGE_BUFFER_DYNAMICs(ShaderParam * shaderParam, const std::vector<RefCountPtr<RHIBuffer>>&buffers, const std::vector<VkDeviceSize>&offsets, const std::vector<VkDeviceSize>&ranges)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(buffers.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(buffers[i].IsValid());
		// descriptorNode.bufferInfos[i].buffer = buffers[i]->GetBuffer();
		descriptorNode.bufferInfos[i].offset = offsets[i];
		descriptorNode.bufferInfos[i].range = ranges[i];
	}
	descriptorNode.buffers.assign(buffers.begin(), buffers.end());
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetINLINE_UNIFORM_BLOCK_EXT(ShaderParam * shaderParam, void* value)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	descriptorNode.inlineWrite.pData = value;
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetACCELERATION_STRUCTURE_KHR(ShaderParam * shaderParam, RefCountPtr<AccelerationStructure> topLevelAS)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(topLevelAS.IsValid());
	descriptorNode.tlasInfos[0] = topLevelAS->GetAccelerationStructure();
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetACCELERATION_STRUCTURE_KHRs(ShaderParam * shaderParam, const std::vector<RefCountPtr<AccelerationStructure>>&topLevelASs)
{
	CheckSetIndex(shaderParam->mSet);
	DescriptorNode& descriptorNode = mDescriptorTable[shaderParam->mSet][shaderParam->mBinging];
	assert(topLevelASs.size() == shaderParam->mCount);
	for (uint32 i = 0; i < shaderParam->mCount; ++i)
	{
		assert(topLevelASs[i].IsValid());
		descriptorNode.tlasInfos[i] = topLevelASs[i]->GetAccelerationStructure();
	}
	descriptorNode.isAssign = true;
}

void RHIDescriptor::SetValueForWrite(uint32 frameIndex, DescriptorNode & descriptorNode)
{
	switch (descriptorNode.descriptorSetLayoutBinding.descriptorType)
	{
	case VK_DESCRIPTOR_TYPE_SAMPLER:
		break;
	case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
	case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
	case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		for (uint32 i = 0; i < descriptorNode.descriptorSetLayoutBinding.descriptorCount; ++i)
		{
			descriptorNode.imageInfos[i].imageView = descriptorNode.textures[i]->GetImageView(frameIndex);
		}
		break;
	case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
		descriptorNode.imageInfos[0].imageView = descriptorNode.textures[0]->GetImageView(frameIndex);
		break;
	case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
		for (uint32 i = 0; i < descriptorNode.descriptorSetLayoutBinding.descriptorCount; ++i)
		{
			descriptorNode.bufferViewInfos[i] = descriptorNode.bufferViews[i]->GetBufferView(frameIndex);
		}
		break;
	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
		for (uint32 i = 0; i < descriptorNode.descriptorSetLayoutBinding.descriptorCount; ++i)
		{
			descriptorNode.bufferInfos[i].buffer = descriptorNode.buffers[i]->GetBuffer(frameIndex);
		}
		break;
	case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT:
		break;
	case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
		break;
	default:
		assert(0);
		break;
	}
}


const VkDescriptorSet& DescriptorMask::GetDescriptorSet() const
{
	if (descriptorSets.size() == 1)
		return descriptorSets[0];
	return descriptorSets[GRenderState->GetFrameIndex()];
}
